﻿using CommonlyUtils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

namespace ImTest
{
    /// <summary>
    /// HttpHelper
    /// </summary>
    public class HttpHelper
    {
        private static object objlock = new object();
        private static HttpClientHelper _localhttp = null;

        public static Dictionary<string, string> BaseHeader = new Dictionary<string, string>()
        {
            { "Content-Type","application/json"}
        };

        private static HttpClientHelper _http
        {
            get
            {
                lock (objlock)
                {
                    if (_localhttp == null)
                    {
                        lock (objlock)
                        {
                            _localhttp = new HttpClientHelper();
                        }
                    }
                    return new HttpClientHelper();
                }
            }
        }

        /// <summary>
        /// 原生Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<string> Get(string url, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader.Add(item.Key, item.Value);
                }
            }
            return (await _http.GetHtmlSync(new HttpItem()
            {
                URL = url,
                Method = "GET",
                Header = httpHeader,
                IsWriteHttpLog = true
            })).Html;
        }

        /// <summary>
        /// 原生Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> GetBase(string url, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader.Add(item.Key, item.Value);
                }
            }
            try
            {
                var apiRes = await _http.GetHtmlSync(new HttpItem()
                {
                    URL = url,
                    Method = "GET",
                    ContentType = "application/json",
                    Header = httpHeader,
                    IsWriteHttpLog = true
                });
                if (apiRes.StatusCode == HttpStatusCode.OK)
                {
                    return (true, apiRes.Html);
                }
                else
                {
                    return (false, apiRes.StatusCode.GetHashCode() + "," + apiRes.StatusDescription);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.Get异常");
                return (false, ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<(string, string)> GetWithCookie(string url, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader.Add(item.Key, item.Value);
                }
            }
            var res = await _http.GetHtmlSync(new HttpItem()
            {
                URL = url,
                Method = "GET",
                Header = httpHeader,
                IsWriteHttpLog = true
            });

            return (res.Html, res.Cookie);
        }

        /// <summary>
        /// 原生Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static async Task<byte[]> GetByte(string url, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader.Add(item.Key, item.Value);
                }
            }
            return (await _http.GetHtmlSync(new HttpItem()
            {
                URL = url,
                Method = "GET",
                Header = httpHeader,
                ResultType = ResultType.Byte
            })).ResultByte;
        }

        /// <summary>
        /// 原生Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="body"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<string> Post(string url, string body, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (BaseHeader.Count() > 0)
            {
                foreach (var item in BaseHeader)
                {
                    httpHeader[item.Key]=item.Value;
                }
            }
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader[item.Key] = item.Value;
                }
            }
           
            try
            {
                var apiRes = await _http.GetHtmlSync(new HttpItem()
                {
                    URL = url,
                    Method = "POST",
                    ContentType = "application/json",
                    Postdata = body,
                    Header = httpHeader,
                    IsWriteHttpLog = true
                });
                if (apiRes.StatusCode == HttpStatusCode.OK)
                {
                    return apiRes.Html;
                }
                else
                {
                    return apiRes.StatusCode.GetHashCode() + "," + apiRes.StatusDescription;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.Post异常");
                return ex.Message;
            }
        }


        /// <summary>
        /// 原生Post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="body"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> PostBase(string url, string body, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (BaseHeader.Count() > 0)
            {
                foreach (var item in BaseHeader)
                {
                    httpHeader[item.Key] = item.Value;
                }
            }
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader[item.Key] = item.Value;
                }
            }

            try
            {
                var apiRes = await _http.GetHtmlSync(new HttpItem()
                {
                    URL = url,
                    Method = "POST",
                    ContentType = "application/json",
                    Postdata = body,
                    Header = httpHeader,
                    IsWriteHttpLog = true
                });
                if (apiRes.StatusCode == HttpStatusCode.OK)
                {
                    return (true, apiRes.Html);
                }
                else
                {
                    return (false, apiRes.StatusCode.GetHashCode() + "," + apiRes.StatusDescription);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.Post异常");
                return (false, ex.Message);
            }
        }

        /// <summary>
        /// 原生Post请求
        /// </summary>
        /// <param name="code"></param>
        /// <param name="body"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> PostForm(string url, Dictionary<string, string> formData, Dictionary<string, string> header = null)
        {
            StringBuilder sb = new StringBuilder();
            try
            {
                sb.AppendLine("PostForm " + url);
                sb.AppendLine("Body：" + formData.ToJson());
                sb.AppendLine("【RequestHeader】");
                sb.AppendLine(header.ToJson());

                // 创建 HttpClient 实例
                using (HttpClient client = new HttpClient())
                {
                    // 将数据转换为 FormUrlEncodedContent
                    var content = new FormUrlEncodedContent(formData);

                    // 创建 HttpRequestMessage 实例
                    var request = new HttpRequestMessage(HttpMethod.Post, url)
                    {
                        Content = content
                    };

                    if (header != null && header.Count > 0)
                    {
                        foreach (var key in header)
                        {
                            // 设置请求头
                            request.Headers.Add(key.Key, key.Value);
                        }
                    }
                    // 发送 POST 请求
                    HttpResponseMessage response = await client.SendAsync(request);
                    // 确保响应成功
                    response.EnsureSuccessStatusCode();

                    sb.AppendLine($"Response：StatusCode:{response.StatusCode},StatusDescription:{response.StatusCode.ToString()},\t{response.Headers.Location?.OriginalString ?? ""}");

                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        // 读取响应内容
                        string responseBody = await response.Content.ReadAsStringAsync();

                        sb.AppendLine("【Html】\r\n" + responseBody);

                        return (true, responseBody);
                    }
                    else
                    {
                        return (false, "Failed：" + response.StatusCode.GetHashCode() + "," + response.StatusCode.ToString());
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.PostForm异常");
                return (false, "Failed：" + ex.Message);
            }
            finally
            {
                LogHelper.WriteLog(sb.ToString());
            }
        }

        /// <summary>
        /// 原生Post请求 发送文件
        /// </summary>
        /// <param name="url">请求Url</param>
        /// <param name="formFile">表单文件 key为 表单字段名 value为文件路径</param>
        /// <param name="formData">表单文件 key为 表单字段名 value为字符串值</param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<(bool, string)> PostFormFile(string url, Dictionary<string, string> formFile, Dictionary<string, string> formData = null, Dictionary<string, string> header = null)
        {
            StringBuilder sb = new StringBuilder();
            try
            {
                sb.AppendLine("PostFormFile " + url);
                sb.AppendLine("File：" + formFile.ToJson());
                sb.AppendLine("FormData：" + formData.ToJson());
                sb.AppendLine("【RequestHeader】");
                sb.AppendLine(header.ToJson());

                // 创建 HttpClient 实例
                using (HttpClient client = new HttpClient())
                {
                    using (var form = new MultipartFormDataContent())
                    {
                        // 读取文件内容
                        foreach (var file in formFile)
                        {
                            var fileStream = new FileStream(file.Value, FileMode.Open, FileAccess.Read);
                            var fileContent = new StreamContent(fileStream);

                            // 设置文件类型
                            fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

                            // 将文件添加到表单数据中，"file"是表单字段名
                            form.Add(fileContent, file.Key, Path.GetFileName(file.Value));
                        }
                        if (formData != null)
                        {
                            foreach (var data in formData)
                            {
                                form.Add(new StringContent(data.Value), data.Key);
                            }
                        }

                        // 发送POST请求
                        var response = await client.PostAsync(url, form);

                        // 确保响应成功
                        response.EnsureSuccessStatusCode();

                        sb.AppendLine($"Response：StatusCode:{response.StatusCode},StatusDescription:{response.StatusCode.ToString()},\t{response.Headers.Location?.OriginalString ?? ""}");

                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            // 读取响应内容
                            string responseBody = await response.Content.ReadAsStringAsync();

                            sb.AppendLine("【Html】\r\n" + responseBody);

                            return (true, responseBody);
                        }
                        else
                        {
                            return (false, "Failed：" + response.StatusCode.GetHashCode() + "," + response.StatusCode.ToString());
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.PostForm异常");
                return (false, "Failed：" + ex.Message);
            }
            finally
            {
                LogHelper.WriteLog(sb.ToString());
            }
        }

        public static async Task<string> PostHtml(string url, string body, Dictionary<string, string> header = null)
        {
            try
            {
                var httpItem = new HttpItem()
                {
                    URL = url,
                    Method = "POST",
                    Postdata = body,
                    IsWriteHttpLog = true
                };

                var httpHeader = new WebHeaderCollection();
                if (header != null && header.Count() > 0)
                {
                    foreach (var item in header)
                    {
                        switch (item.Key.ToLower().Trim())
                        {
                            case "user-agent":
                                httpItem.UserAgent = item.Value;
                                break;
                            case "content-type":
                                httpItem.ContentType = item.Value;
                                break;
                            case "host":
                            case "accept":
                            case "referer":
                            case "content-length":
                            case "connection":
                                break;
                            default:
                                httpHeader.Add(item.Key, item.Value);
                                break;
                        }
                        //httpHeader.Add(item.Key, item.Value);
                    }
                }
                httpItem.Header = httpHeader;
                var apiRes = await _http.GetHtmlSync(httpItem);
                if (apiRes.StatusCode == HttpStatusCode.OK)
                {
                    return apiRes.Html;
                }
                else
                {
                    return apiRes.StatusCode.GetHashCode() + "," + apiRes.StatusDescription;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.Post异常");
                return ex.Message;
            }
        }

        public static async Task<string> PostHtml(HttpItem httpItem)
        {
            try
            {
                var apiRes = await _http.GetHtmlSync(httpItem);
                if (apiRes.StatusCode == HttpStatusCode.OK)
                {
                    return apiRes.Html;
                }
                else
                {
                    return apiRes.StatusCode.GetHashCode() + "," + apiRes.StatusDescription;
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex, "HttpHelper.Post异常");
                return ex.Message;
            }
        }


        /// <summary>
        /// 回调 自动重试3次
        /// </summary>
        /// <param name="url"></param>
        /// <param name="body"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        public static async Task<string> CallBack(string url, string body, Dictionary<string, string> header = null)
        {
            var httpHeader = new WebHeaderCollection();
            if (header != null && header.Count() > 0)
            {
                foreach (var item in header)
                {
                    httpHeader.Add(item.Key, item.Value);
                }
            }

            int idx = 1;
            var reshtml = "";
            while (idx <= 6)
            {
                try
                {
                    var res = await _http.GetHtmlSync(new HttpItem()
                    {
                        URL = url,
                        Method = "POST",
                        ContentType = "application/json",
                        Postdata = body,
                        Header = httpHeader,
                        IsWriteHttpLog = true
                    });
                    if (res.StatusCode == HttpStatusCode.OK)
                    {
                        reshtml = res.Html;
                        return $"通知第{idx}次:" + reshtml;
                    }
                    else
                    {
                        reshtml = res.StatusCode.GetHashCode() + res.StatusDescription;
                    }
                    await Task.Delay(5000);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(ex, $"通知第{idx}失败:" + ex.Message);
                    reshtml = ex.Message;
                }
                idx++;
            }
            return $"通知第{idx}次:" + reshtml;
        }
    }
}
